package org.qianji.goosql.cond;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.qianji.goosql.field.Field;
import org.qianji.goosql.operator.Comparator;

/**
 * 通用字段间比较查询条件，支持小于、大于、小于等于、大于等于、等于、不等于五个比较运算。
 * 
 * @author gmz
 * 
 */
public class FieldCondition extends AbstractCondition {

	/**
	 * 
	 */
	private static final long serialVersionUID = 5370337303452894742L;

	@SuppressWarnings("serial")
	public static final Set<Comparator> acceptedComparators = new HashSet<Comparator>() {
		{
			add(Comparator.LT);
			add(Comparator.GT);
			add(Comparator.LE);
			add(Comparator.GE);
			add(Comparator.EQ);
			add(Comparator.NE);
		}
	};

	private Field leftField;
	private Comparator comparator;
	private Field rightField;

	/**
	 * 根据左字段、右字段、比较运算符构造查询条件。
	 * 
	 * @param leftField
	 *            {@link Field} 左字段
	 * @param comparator
	 *            {@link Comparator} 比较运算符，只需是小于、大于、小于等于、大于等于、等于或不等于
	 * @param rightField
	 *            {@link Field} 右字段
	 */
	public FieldCondition(Field leftField, Comparator comparator, Field rightField) {
		super();
		if (leftField == null || comparator == null || rightField == null) {
			throw new NullPointerException("the args can't be null");
		}
		if (!acceptedComparators.contains(comparator)) {
			throw new IllegalArgumentException("the comparator is illegal");
		}
		this.leftField = leftField;
		this.comparator = comparator;
		this.rightField = rightField;
	}

	/**
	 * 获取左字段。
	 * 
	 * @return {@link Field} 左字段
	 */
	public Field getLeftField() {
		return leftField;
	}

	/**
	 * 获取比较运算符。
	 * 
	 * @return {@link Comparator} 比较运算符
	 */
	public Comparator getComparator() {
		return comparator;
	}

	/**
	 * 获取右字段。
	 * 
	 * @return {@link Field} 右字段
	 */
	public Field getRightField() {
		return rightField;
	}

	@Override
	public String toSql() {
		StringBuffer cond = new StringBuffer();
		cond.append(leftField.toSql()).append(" ").append(comparator).append(" ").append(rightField.toSql());
		return cond.toString();
	}

	@Override
	public List<Object> getPlacedParameters() {
		List<Object> ppl = new ArrayList<Object>();
		ppl.addAll(leftField.getPlacedParameters());
		ppl.addAll(rightField.getPlacedParameters());
		return ppl;
	}

	@Override
	public Map<String, Object> getNamedParameters() {
		Map<String, Object> npm = new HashMap<String, Object>();
		npm.putAll(leftField.getNamedParameters());
		npm.putAll(rightField.getNamedParameters());
		return npm;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null || !(obj instanceof FieldCondition)) {
			return false;
		}
		FieldCondition other = (FieldCondition) obj;
		if (leftField.equals(other.getLeftField()) && rightField.equals(other.getRightField())
				&& comparator.equals(other.getComparator())) {
			return true;
		}
		return false;
	}

	@Override
	public int hashCode() {
		int hc = 37 * 17 + leftField.hashCode();
		hc = 37 * hc + comparator.hashCode();
		hc = 37 * hc + rightField.hashCode();
		return hc;
	}

	@Override
	public String toString() {
		return toSql();
	}

}
